package org.hilo.boot.core;

import java.util.List;
import java.util.Map;

import org.jretty.apibase.PagerData;
import org.hilo.boot.core.exception.NotImplementedException;
import org.hilo.boot.core.mapper.DeleteByIdsMapper;
import org.hilo.boot.core.mapper.SelectByIdsMapper;
import org.hilo.boot.core.mapper.SelectByParamMapper;
import org.hilo.boot.core.mapper.UpdateByIdsMapper;
import org.hilo.boot.core.mapper.UpdateByRecordMapper;
import org.hilo.boot.core.value.ActionType;
import org.hilo.boot.core.value.ObjectInitValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.github.pagehelper.ISelect;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import tk.mybatis.mapper.common.special.InsertListMapper;

/**
 * 基于Mybatis Mapper的公用Data Managing Service，封装一些 常用且公用 的方法
 * 
 * @author zollty
 * @since 2016-11-20
 */
public abstract class BaseDms<T, M extends BaseMapper<T>> implements MapperDms<T> {

    @Autowired
    protected BaseMapper<T> baseMapper;
    
    @Autowired(required = false)
    @Qualifier("objInit")
    protected ObjectInitValue objInit;
    
    /**
     * @see ObjectInitValue
     * @return 对象初始化实现类
     */
    protected ObjectInitValue getObjInit() {
        return objInit;
    }
    
    /**
     * @param type 0为新增，1为更新
     */
    protected void initValue(T record, int type) {
        if (objInit != null) {
            objInit.initValue(record, type);
        }
    }
    
    @SuppressWarnings("unchecked")
    protected M mapper() {
        return (M) baseMapper;
    }

    @Override
    public T selectOne(T record) {
        return baseMapper.selectOne(record);
    }

    @Override
    public T selectByPrimaryKey(Object key) {
        return baseMapper.selectByPrimaryKey(key);
    }

    @Override
    public int selectCount(T record) {
        return baseMapper.selectCount(record);
    }

    @Override
    public List<T> selectAll() {
        return baseMapper.selectAll();
    }

    @Override
    public List<T> select(T record) {
        return baseMapper.select(record);
    }
    
    public PagerData<T> selectByPage(int pageNum, int pageSize, final T record) {
        Page<T> page = PageHelper.startPage(pageNum, pageSize)
                .doSelectPage(new ISelect() {
            @Override
            public void doSelect() {
                baseMapper.select(record);
            }
        });
        return PagerData.create(page.getResult(), pageSize, pageNum, (int) page.getTotal());
    }

    @SuppressWarnings("unchecked")
    public List<T> selectByParam(Map<String, ?> param) {
        if (baseMapper instanceof SelectByParamMapper) {
            return ((SelectByParamMapper<T>) baseMapper).selectByParam(param);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the SelectByParamMapper interface!");
    }

    public PagerData<T> selectByPage(int pageNum, int pageSize, final Map<String, ?> param) {
        
        if (baseMapper instanceof SelectByParamMapper) {
            Page<T> page = PageHelper.startPage(pageNum, pageSize).doSelectPage(new ISelect() {
                @SuppressWarnings("unchecked")
                @Override
                public void doSelect() {
                    ((SelectByParamMapper<T>) baseMapper).selectByParam(param);
                }
            });
            return PagerData.create(page.getResult(), pageSize, pageNum, (int) page.getTotal());
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the SelectByParamMapper interface!");
    }
    
    /**
     * 根据主键更新属性不为null的值
     */
    @SuppressWarnings({ "unchecked" })
    public List<T> selectByIds(List<?> ids) {
        if (baseMapper instanceof SelectByIdsMapper) {
            return ((SelectByIdsMapper<T>) baseMapper).selectByIds(ids);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the UpdateByIdsMapper interface!");
    }

    @Override
    public boolean existsWithPrimaryKey(Object key) {
        return baseMapper.existsWithPrimaryKey(key);
    }

    @Override
    public int delete(T record) {
        return baseMapper.delete(record);
    }

    @Override
    public int deleteByPrimaryKey(Object key) {
        return baseMapper.deleteByPrimaryKey(key);
    }

    @SuppressWarnings({ "unchecked" })
    public int deleteByIds(List<?> ids) {
        if (baseMapper instanceof DeleteByIdsMapper) {
            return ((DeleteByIdsMapper<T>) baseMapper).deleteByIds(ids);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the DeleteByIdsMapper interface!");
    }

    @Override
    public int insert(T record) {
        initValue(record, ActionType.ADD);
        return baseMapper.insertSelective(record);
    }

    @Override
    public int insertNull(T record) {
        return baseMapper.insert(record);
    }
    
    /**
     * 批量插入，支持批量插入的数据库可以使用，例如MySQL,H2等，
     * 另外该接口限制实体包含`id`属性并且必须为自增列
     */
    @SuppressWarnings({ "unchecked" })
    public int insertList(List<T> recordList) {
        if (baseMapper instanceof InsertListMapper) {
            for(T record: recordList) {
                initValue(record, ActionType.ADD);
            }
            return ((InsertListMapper<T>) baseMapper).insertList(recordList);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the InsertListMapper interface!");
    }

    @Override
    public int update(T record) {
        initValue(record, ActionType.UPDATE);
        return baseMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateNull(T record) {
        return baseMapper.updateByPrimaryKey(record);
    }

    /**
     * 根据主键更新属性不为null的值
     */
    @SuppressWarnings({ "unchecked" })
    public int updateByIds(T record, List<?> ids) {
        if (baseMapper instanceof UpdateByIdsMapper) {
            initValue(record, ActionType.UPDATE);
            return ((UpdateByIdsMapper<T>) baseMapper).updateByIds(record, ids);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the UpdateByIdsMapper interface!");
    }

    /**
     * 根据param更新属性不为null的值
     */
    @SuppressWarnings("unchecked")
    public int updateByRecord(T record, T param) {
        if (baseMapper instanceof UpdateByRecordMapper) {
            initValue(record, ActionType.UPDATE);
            return ((UpdateByRecordMapper<T>) baseMapper).updateByRecord(record, param);
        }
        throw new NotImplementedException(
                "the class " + baseMapper.getClass() 
                + " does not implemented the UpdateByRecordMapper interface!");
    }

}
